package cn.cutie.clot.fs;

import com.alibaba.fastjson.JSON;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.DigestUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.HashMap;

/**
 * @Description:
 * @Author: Cutie
 * @CreateDate: 2024/7/16 09:24
 * @Version: 0.0.1
 */
@RestController
@RequestMapping("/file")
public class FileController {
    @Value("${clotfs.path}")
    private String uploadPath;

    @Value("${clotfs.backupUrl}")
    private String backupUrl;

    @Value("${clotfs.downloadUrl}")
    private String downloadUrl;

    @Value("${clotfs.autoMd5}")
    private Boolean autoMd5;

    @Value("${clotfs.syncBackup}")
    private Boolean syncBackup;

    @Autowired
    private HttpSyncer httpSyncer;

    @Autowired
    MQSyncer mqSyncer;

    @SneakyThrows
    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
        // 1. 处理文件
        boolean needSync = false;
        String filename = request.getHeader(HttpSyncer.X_FILE_NAME);
        String originalFilename = file.getOriginalFilename();

        if (filename == null || filename.isEmpty()){ // 上传文件
            needSync = true;
//            filename = file.getOriginalFilename();
            filename = FileUtils.getUUIDFile(originalFilename);
        } else { // 同步文件
            String xor = request.getHeader(HttpSyncer.X_ORIGIN_FILE_NAME);
            if (xor != null && !xor.isEmpty()){
                // 获取真实的文件名
                originalFilename = xor;
            }
        }
        String subDir = FileUtils.getSubDir(filename);
        File dest = new File(uploadPath + "/" + subDir + "/" + filename);
        file.transferTo(dest);

        FileMeta fileMeta = FileMeta.builder()
                .name(filename)
                .originalName(originalFilename)
                .size(file.getSize())
                .tags(new HashMap<>())
                .downloadUrl(downloadUrl)
                .build();
        // 2. 处理mata信息
        if (autoMd5){
            fileMeta.getTags().put("md5", DigestUtils.md5DigestAsHex(new FileInputStream(dest)));
        }

        // 2.1 存放到本地文件
        String mataName = filename + ".meta";
        File metaFile = new File(uploadPath + "/" + subDir + "/" + mataName);
        FileUtils.writeMeta(metaFile, fileMeta);

        // 2.2 存放到数据库
        // 2.3 存放到配置中心或者注册中心，比如zk


        // 3. 同步文件到backup
        // 可以实现同步处理文件复制，也可以异步处理文件复制
        if (needSync){
            if (syncBackup){ // 同步
                try{
                    httpSyncer.sync(dest, backupUrl, originalFilename);
                } catch (Exception e){
                    // 记录异常
                    // 异步处理
//                    MQSyncer.sync(backupUrl, mataName, originalFilename);
                }
            } else { // 异步，mq实现
                mqSyncer.sync(fileMeta);
            }
        }
        return filename;
    }

    @RequestMapping("/download")
    public void download(String filename, HttpServletResponse response) {
        String subDir = FileUtils.getSubDir(filename);
        String path = uploadPath + "/" + subDir + "/" + filename;
        File file = new File(path);
        try {
            FileInputStream fis = new FileInputStream(file);
            InputStream is = new BufferedInputStream(fis);
            byte[] buffer = new byte[16*1024];
            // 添加response头，告诉浏览器以附件形式下载
            response.setCharacterEncoding("UTF-8");
//            response.setContentType("application/octet-stream");
//            response.setContentType("image/png");
            response.setContentType(FileUtils.getMimeType(filename));
            // 是否以附件形式
//            response.setHeader("Content-Disposition", "attachment;filename=" + new String(name.getBytes(), "UTF-8"));
            response.setHeader("Content-Length", String.valueOf(file.length()));
            OutputStream os = response.getOutputStream();
            while (is.read(buffer) != -1) {
                os.write(buffer);
            }
            os.flush();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @SneakyThrows
    @RequestMapping("/meta")
    public String meta(String filename) {
        String subDir = FileUtils.getSubDir(filename);
        String path = uploadPath + "/" + subDir + "/" + filename + ".meta";
        File file = new File(path);
        return FileCopyUtils.copyToString(new FileReader(file));
    }

}
